package com.zhb.cloud.config;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhb.cloud.message.listener.RedisMessageListener;

/**
 * @ClassName: RedisConfig
 * @Description: redis 基本配置
 * @author: zhb zhb1316783262@163.com
 * @date: 2017年11月14日 下午3:53:05
 *
 */
@Configuration
@EnableCaching
public class RedisConfig {
	/**
	 * @Title: redisTemplate
	 * @Description: 操作模板
	 * @return: RedisTemplate<Object,Object>
	 * @param: @return
	 * @author: zhb
	 * @throws 2016年3月6日下午8:11:33
	 */
	@Autowired
	private RedisConnectionFactory redisConnectionFactory;

	/**
	 * 通用操作模板RedisTemplate
	 * 
	 * @return
	 */
	public @Bean RedisTemplate<String, Object> sessionRedisTemplate() {
		RedisTemplate<String, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		RedisSerializer<String> stringSerializer = new StringRedisSerializer();
		template.setKeySerializer(stringSerializer);
		template.setValueSerializer(sessionRedisSerializer());
		template.setHashKeySerializer(stringSerializer);
		template.setHashValueSerializer(sessionRedisSerializer());
		template.afterPropertiesSet();
		return template;
	}

	/**
	 * @Description: String 类型操作模板
	 * @return
	 */
	public @Bean StringRedisTemplate stringRedisTemplate() {
		StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisConnectionFactory);
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
				Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);
		stringRedisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
		stringRedisTemplate.afterPropertiesSet();
		return stringRedisTemplate;
	}

	/**
	 * 设置redisTemplate的存储格式（在此与Session没有什么关系）
	 * 
	 * @return
	 */
	public @Bean RedisSerializer<Object> sessionRedisSerializer() {
		return new Jackson2JsonRedisSerializer<Object>(Object.class);
	}

	/**
	 * 缓存管理
	 */
	public @Bean CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
		return new RedisCacheManager(redisTemplate);
	}

	/**
	 * 缓存key生成器
	 * 
	 * @return
	 */
	public @Bean KeyGenerator commonKeyGenerator() {
		return new KeyGenerator() {
			@Override
			public Object generate(Object target, Method method, Object... params) {
				StringBuilder sb = new StringBuilder();
				sb.append(target.getClass().getName());
				sb.append(method.getName());
				for (Object obj : params) {
					sb.append(obj.toString());
				}
				String key = sb.toString();
				return key;
			}
		};
	}

	/**
	 * @Title: getTopic
	 * @Description: 聊天室
	 * @return: Topic
	 * @param: @return
	 * @author: zhb
	 * @throws 2016年4月14日上午9:54:45
	 */
	public @Bean(name = "topic") Topic getTopic() {
		return new ChannelTopic("chart");
	}

	/**
	 * @Title: getMessageListenerAdapter
	 * @Description: 消息监听器
	 * @return: MessageListenerAdapter
	 * @author: zhb
	 * @throws 2016年4月14日上午9:40:10
	 */
	public @Bean(name = "messageListener") MessageListenerAdapter getMessageListenerAdapter() {
		return new RedisMessageListener();
	}

	/**
	 * @Title: getRedisMessageListenerContainer
	 * @Description: 获得redis消息监听容器
	 * @return: RedisMessageListenerContainer
	 * @param: @return
	 * @author: zhb
	 * @throws 2016年4月14日上午9:41:09
	 */
	public @Bean(name = "redisContainer") RedisMessageListenerContainer getRedisMessageListenerContainer() {
		Map<MessageListenerAdapter, Collection<? extends Topic>> listeners = new HashMap<>();
		List<Topic> topics = new ArrayList<>();
		topics.add(getTopic());
		listeners.put(getMessageListenerAdapter(), topics);
		RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
		listenerContainer.setConnectionFactory(redisConnectionFactory);
		listenerContainer.setMessageListeners(listeners);
		return listenerContainer;
	}
}